package com.cloudlead.common.worker.web;

import com.cloudlead.common.lang.ObjectStatus;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by dean on 2015/7/29.
 */
public class WorkerRegistry {
    private static final Logger LOGGER = LoggerFactory.getLogger(WorkerRegistry.class);
    private Map<String, WorkerInfo> workers = new ConcurrentHashMap<>();
    private Map<String, String> actionWorkerMap = new ConcurrentHashMap<>();
    private Map<String, String> moduleFacadeWorkerMap = new ConcurrentHashMap<>();

    private static WorkerRegistry singleInstance;

    private WorkerRegistry() {
    }

    public synchronized static WorkerRegistry getInstance() {
        if (null == singleInstance) {
            singleInstance = new WorkerRegistry();
        }
        return singleInstance;
    }

    public void addWorker(String workerToken, WorkerInfo workerInfo) {
        Iterator<Map.Entry<String, WorkerInfo>> iterator = workers.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, WorkerInfo> next = iterator.next();
            WorkerInfo value = next.getValue();
            if (value.getWorkerName().equals(workerInfo.getWorkerName())) {
                removeWorker(next.getKey());
                break;
            }
        }
        LOGGER.debug("Add worker [" + workerToken + "]");
        workers.put(workerToken, workerInfo);
        for (String action : workerInfo.getActions().keySet()) {
            actionWorkerMap.put(action, workerToken);
        }
        for (Map.Entry<String, Set<String>> module : workerInfo.getModules().entrySet()) {
            Set<String> moduleFacades = module.getValue();
            if (null != moduleFacades) {
                moduleFacades.stream().filter(moduleFacade -> StringUtils.isNotBlank(moduleFacade)).forEach(moduleFacade -> {
                    moduleFacadeWorkerMap.put(moduleFacade, module.getKey());
                });
            }
        }
    }

    public void removeWorker(String workerToken) {
        WorkerInfo workerInfo = workers.get(workerToken);
        if (null != workerInfo) {
            LOGGER.debug("Remove worker [" + workerToken + "]");
            Map<String, List<String>> actions = workerInfo.getActions();
            actions.keySet().forEach(actionWorkerMap::remove);
            Map<String, Set<String>> modules = workerInfo.getModules();
            Collection<Set<String>> values = modules.values();
            for (Set<String> facades : values) {
                facades.forEach(moduleFacadeWorkerMap::remove);
            }
            workers.remove(workerToken);
        }
    }

    public void disableWorker(String workerToken) {
        WorkerInfo workerStatus = workers.get(workerToken);
        if (null != workerStatus) {
            workerStatus.setStatus(ObjectStatus.disabled);
        }
    }

    public void enableWorker(String workerToken) {
        WorkerInfo workerStatus = workers.get(workerToken);
        if (null != workerStatus) {
            workerStatus.setStatus(ObjectStatus.enabled);
        }
    }

    public Map<String, WorkerInfo> getWorkerList() {
        return workers;
    }

    public String findWorker(String action) {
        return actionWorkerMap.get(action);
    }

    public String findModule(String facade) {
        return moduleFacadeWorkerMap.get(facade);
    }
}
